package ginx

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"go.uber.org/zap"
	"net/http"
	"strconv"
)

var vector *prometheus.CounterVec

func NewCounter(namespace string, subsystem string, name string, help string, instanceID string) {
	vector = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: namespace,
		Subsystem: subsystem,
		Name:      name,
		Help:      help,
		ConstLabels: map[string]string{
			"idstance_id": instanceID,
		},
	}, []string{"code"})
	prometheus.MustRegister(vector)
}
func Wrap(fn func(ctx *gin.Context) (Result, error)) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		res, err := fn(ctx)

		if err != nil {
			zap.L().Error("处理业务逻辑错误：",
				zap.String("path", ctx.Request.URL.Path),
				zap.String("route", ctx.FullPath()),
				zap.Error(err))
		}
		fmt.Println(res)
		ctx.JSON(http.StatusOK, res)
	}
}
func WrapBody[T any](fn func(ctx *gin.Context, req T) (Result, error)) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		var req T
		if err := ctx.Bind(&req); err != nil {
			zap.L().Info("反序列化请求失败:", zap.Error(err))
			return
		}
		res, err := fn(ctx, req)

		if err != nil {
			zap.L().Error("处理业务逻辑错误：",
				zap.String("path", ctx.Request.URL.Path),
				zap.String("route", ctx.FullPath()),
				zap.Error(err))
		}
		fmt.Println(res)
		ctx.JSON(http.StatusOK, res)
	}
}
func WrapBodyAndToken[T any, C any](fn func(ctx *gin.Context, req T, uc C) (Result, error)) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		var req T
		var uc C
		fmt.Printf("%T %T", req, uc)
		if err := ctx.Bind(&req); err != nil {
			zap.L().Info("反序列化请求失败:", zap.Error(err))
			return
		}

		val, ok := ctx.Get("claims")
		if !ok {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			zap.L().Error("未获取到用户session信息")
			return
		}
		claims, ok := val.(C)
		if !ok {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			zap.L().Error("断言失败")
			return
		}
		res, err := fn(ctx, req, claims)
		if err != nil {
			zap.L().Error("处理业务逻辑错误：",
				zap.String("path", ctx.Request.URL.Path),
				zap.String("route", ctx.FullPath()),
				zap.Error(err))
		}
		vector.WithLabelValues(strconv.Itoa(res.Code)).Inc()
		ctx.JSON(http.StatusOK, res)
	}
}
func WrapToken[C any](fn func(ctx *gin.Context, uc C) (Result, error)) gin.HandlerFunc {
	return func(ctx *gin.Context) {

		val, ok := ctx.Get("claims")
		if !ok {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			zap.L().Error("未获取到用户session信息")
			return
		}
		claims, ok := val.(C)
		if !ok {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			zap.L().Error("断言失败")
			return
		}
		res, err := fn(ctx, claims)
		if err != nil {
			zap.L().Error("处理业务逻辑错误：",
				zap.String("path", ctx.Request.URL.Path),
				zap.String("route", ctx.FullPath()),
				zap.Error(err))
		}
		ctx.JSON(http.StatusOK, res)
	}
}

type Result struct {
	Code int    `json:"code"`
	Data any    `json:"data"`
	Msg  string `json:"msg"`
}
